using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace DoVuiKinhThanh {

    /// <summary>
    /// Common base class for view model using change tracking.
    /// </summary>
    public abstract class ChangeTrackingViewModelBase : ViewModelBase, IChangeTracking, IDataErrorInfo {
        #region IFields

        private bool m_isChanged;

        #endregion IFields
        #region IConstructors

        /// <summary>
        /// Constructor
        /// </summary>
        public ChangeTrackingViewModelBase() {
            PropertyChanged += UpdateChangeStateOnPropertyChanged;
        }

        #endregion IConstructors
        #region IMethods

        /// <summary>
        /// Member of IDataErrorInfo interface
        /// </summary>
        /// <param name="propertyName">The Property Name</param>
        string IDataErrorInfo.this[string propertyName] {
            get {
                return GetValidationError(propertyName);
            }
        }

        /// <summary>
        /// Get error message when validating property
        /// </summary>
        /// <param name="propertyName">The Property Name</param>
        protected virtual string GetValidationError(string propertyName) {
            return null;
        }

        /// <summary>
        /// Check data of ViewModel is valid
        /// </summary>
        public bool IsDataValid() {
            foreach (string property in ValidatedProperties) {
                if (GetValidationError(property) != null) {
                    return false;
                }                    
            }               
            return true;
        }

        #endregion IMethods
        #region IProperties

        public bool IsChanged {
            get {
                return m_isChanged;
            }
            protected set {
                if (m_isChanged != value) {
                    m_isChanged = value;
                    OnPropertyChanged(() => IsChanged);
                }
            }
        }

        /// <summary>
        /// Member of interface IDataErrorInfo
        /// </summary>
        public string Error {
            get {
                return string.Empty;
            }
        }

        /// <summary>
        /// Properties of ViewModel which must be validated
        /// </summary>
        public virtual string[] ValidatedProperties {
            get { return null; }
        }

        /// <summary>
        /// Ignore detect changes on these properties
        /// </summary>
        public virtual IList<string> IgnoredProperties {
            get {
                return new string[] { };
            }  
        }

        #endregion IProperties
        #region IMethods

        public virtual void AcceptChanges() {
            IsChanged = false;
        }

        private void UpdateChangeStateOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
            if (e != null && !IgnoredProperties.Contains(e.PropertyName)  
                && !String.Equals(e.PropertyName, "IsChanged", StringComparison.Ordinal)) {
                
                IsChanged = true;
            }
        }

        #endregion
    }
}